//
//  HD_NKM_Mediator.m
//  HDWuDaDaoServiceCenter
//
//  Created by HDNiuKuiming on 2017/5/12.
//  Copyright © 2017年 HDNiuKuiming. All rights reserved.
//

#import "HD_NKM_Mediator.h"

@interface HD_NKM_Mediator()

@property (strong, nonatomic) NSMutableDictionary *beacons;
@property (strong, nonatomic) CLLocationManager   *locationManager;
@property (strong, nonatomic) NSMutableDictionary *rangedRegions;
@property (strong, nonatomic) NSNumber            *beaconNum;    // 单点定位时抛出的蓝牙号，用于隔一

@property (strong, nonatomic) NSDate         *noBeaconStartTime; // 计时器，暂未开发
@property (strong, nonatomic) NSDate         *noBeaconEndTime;   // 计时器，暂未开发
@property (strong, nonatomic) NSMutableArray *topBeaconArray;    // 计算距离的数组
@property (strong, nonatomic) NSMutableSet   *valideVCSet;       // 是否为触发蓝牙的界面
@property (assign, nonatomic) CGFloat        playDis;            // 距离，用于蓝牙算法

@end

@implementation HD_NKM_Mediator

#pragma mark
#pragma mark -------- Init Methods ---------

+ (id)shareInstance
{
    static id shareMediator;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareMediator = [[self alloc] init];
    });
    
    return shareMediator;
}

- (instancetype)init
{
    self = [super init];
    
    if (self) {
        successSwitch           = YES;
        ThreshHold_Dis          = 10.0f;
        No_Beacon_Last_Time     = 300;
        Max_Successive_Distance = 10.0f;  
        Gather_Data_Cnt         = 2;      
        iBeacon_Num_Max         = 65535;  
        iBeacon_Num_Min         = 1;
        succussiveBeaconCount   = 0;
        _valideVCSet    = [[NSMutableSet alloc] init];
        _topBeaconArray = [[NSMutableArray alloc] initWithCapacity:2];
        [self initBeacon];
    }
    
    return self;
}

+ (void)initValideVCList:(NSString *)vcClassStr
{
    NSMutableSet *strSet = [[HD_NKM_Mediator shareInstance] valideVCSet];
    [strSet addObject:vcClassStr];
}

- (BOOL)isValideVC
{
    BOOL isValide = NO;
    for (NSString *vcStr in _valideVCSet) {
        if ([vcStr.uppercaseString isEqualToString:_nowVCString.uppercaseString]) {
            isValide = YES;
            break;
        }
    }
    
    return isValide;
}

+ (void)setNowVCDescription:(NSString *)VCStr
{  [[HD_NKM_Mediator shareInstance] setNowVCString:VCStr]; }

- (void)setNowVCString:(NSString *)nowVCString
{
    _nowVCString = nowVCString;
    [self cleanPlayNum]; // 只要切换页面，当前收的号置空
}

#pragma mark
#pragma mark -------- IBeacon Methods --------

- (void)initBeacon
{
    self.beacons = [[NSMutableDictionary alloc] init];
    
    // This location manager will be used to demonstrate how to range beacons.
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        [self.locationManager requestWhenInUseAuthorization];
    }
    
    // Populate the regions we will range once.
    self.rangedRegions = [[NSMutableDictionary alloc] init];
    
    for (NSUUID *uuid in [APLDefaults sharedDefaults].supportedProximityUUIDs) {
        CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:[uuid UUIDString]];
        self.rangedRegions[region] = [NSArray array];
    }
}

- (void)startRangingAllRegions
{
    [self stopRangingAllRegions];
    
    for (CLBeaconRegion *region in self.rangedRegions) {
        [self.locationManager startRangingBeaconsInRegion:region];
    }
}

- (void)stopRangingAllRegions
{
    for (CLBeaconRegion *region in self.rangedRegions) {
        [self.locationManager stopRangingBeaconsInRegion:region];
    }
}

#pragma mark
#pragma mark -------- Location Delegate --------


- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    // 线程运行
    dispatch_async(dispatch_get_main_queue(), ^{
        
        if (beacons.count > 0 && [self isValideVC]) {
            self.rangedRegions[region] = beacons;
            [self.beacons removeAllObjects];
            
            NSMutableArray *allBeacons = [NSMutableArray array];
            for (NSArray *regionResult in [self.rangedRegions allValues]) {
                [allBeacons addObjectsFromArray:regionResult];
            }
            
            for (int i=0; i< allBeacons.count;i++) {
                CLBeacon *beacon = allBeacons[i];
                if (beacon.accuracy<0 || beacon.accuracy > ThreshHold_Dis) {
                    [allBeacons removeObject:beacon];
                }
            }
            
            if (allBeacons.count == 0) // 单点定位
                return;
            
            NSArray *sortArray = [allBeacons sortedArrayUsingComparator:^NSComparisonResult(CLBeacon *p1, CLBeacon *p2){
                NSString *p1Str = [NSString stringWithFormat:@"%f", p1.accuracy];
                NSString *p2Str = [NSString stringWithFormat:@"%f", p1.accuracy];
                return [p1Str compare:p2Str];
            }];
            
            // 去除干扰号
            NSArray *unknownBeacons = [sortArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"proximity != %d ", CLProximityUnknown]];
            [self beaconCalculateAction:unknownBeacons];
            
            if (succussiveBeaconCount > 0) {
                [self successiveBeaconNotifiactionAction:unknownBeacons]; // 连续定位
            }
        }
    });
}

- (void)beaconCalculateAction:(NSArray *)beaconArray
{
    if (beaconArray.count > 0) {
        // 根据楼层算距离
        CGFloat beaconDis = ThreshHold_Dis;
        beaconDis *= [self distanceMutiple]; // 根据不同机型，设定不同距离
        
        dispatch_queue_t  queue= dispatch_queue_create("hengdaIBeacon", NULL);
        dispatch_async(queue, ^{
            CLBeacon *firstBeacon = nil;
            for (NSInteger i=0;i<beaconArray.count;i++) {
                CLBeacon *tempBeacon = beaconArray[i];
                if (tempBeacon.accuracy<beaconDis && tempBeacon.minor.integerValue < iBeacon_Num_Max) {
                    firstBeacon = tempBeacon;
                    break;
                }
            }
            
            if (firstBeacon != nil) {
                NSString *postStr = [self pipeBeacon:firstBeacon];
                if (postStr != nil) {
                    [self pipeMapNotification:firstBeacon.minor];
                    //[self pipeBeaconNotification:firstBeacon]; // 测试工具
                }
            }
        });
    }
}

// 上传连续定位信息，抛出消息
- (void)successiveBeaconNotifiactionAction:(NSArray *)beaconArray
{
    NSArray *successArray = beaconArray;
    if (successArray.count > succussiveBeaconCount) {
        successArray = [beaconArray subarrayWithRange:NSMakeRange(0, 5)];
    }
    
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", nil);
    dispatch_async(myQueue, ^{
        
        if (nowSuccessiveType == kSuccessive_Type_Per_1_Sec) {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"kSuccessive_Location_Beacon_Notification" object:successArray];
//#error @"所有的通知需要到公共的.h文件中去定义，不要随意的放在文件中"
        }
        else if (nowSuccessiveType == kSuccessive_Type_Per_2_Sec ) {
            if ( successSwitch == YES) {
                [[NSNotificationCenter defaultCenter] postNotificationName:@"kSuccessive_Location_Beacon_Notification" object:successArray];
//#error @"所有的通知需要到公共的.h文件中去定义，不要随意的放在文件中"
            }
            
            successSwitch = !successSwitch; // 系统一秒钟发一次蓝牙号
        }
    });

}

// 连续收两次beacon号码，如果两组号码一致，就触发
- (NSString *)pipeBeacon:(CLBeacon *)firstBeacon
{
    NSString *postBeaconStr = nil;
    NSString *beaconStr = [NSString stringWithFormat:@"%li",(long)firstBeacon.minor.integerValue];
    if (_topBeaconArray.count == 0 ) {
        [_topBeaconArray addObject:beaconStr];
        _playDis = firstBeacon.accuracy;
    }
    else if (_topBeaconArray.count == 1 ) {
        NSString *strA = _topBeaconArray[0];
        if (strA.integerValue == beaconStr.integerValue)
        {
            [_topBeaconArray addObject:beaconStr];
            postBeaconStr = beaconStr;
            CGFloat tempDis = (_playDis + firstBeacon.accuracy)/2;
            _playDis = tempDis;
        }
        else if (firstBeacon.accuracy < _playDis)
        {
            [_topBeaconArray removeObjectAtIndex:0];
            [_topBeaconArray addObject:beaconStr];
            _playDis = firstBeacon.accuracy;
        }
    }
    else {
        [_topBeaconArray removeAllObjects];
    }
    
    return postBeaconStr;
}

-(void)pipeMapNotification:(NSNumber*)postNum
{
    if(self.beaconNum.integerValue != postNum.integerValue && [self isValideVC]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:iBeacon_Send_Notification object:postNum]; // 抛出消息，用于地图定位
        self.beaconNum = postNum;
    }
}

-(void)pipeBeaconNotification:(CLBeacon*)postBeacon
{
    NSString *minor = [NSString stringWithFormat:@"%@",postBeacon.minor];
    NSString *major = [NSString stringWithFormat:@"%@",postBeacon.major];
    NSString *distance = [NSString stringWithFormat:@"%f",postBeacon.accuracy];
    NSDictionary *testBeaconDic = @{@"minor":minor,
                                    @"major":major,
                                    @"distance":distance};
    [[NSNotificationCenter defaultCenter] postNotificationName:iBeacon_Dic_Send_Notification object:testBeaconDic]; // 抛出消息，用于地图定位
}

#pragma mark
#pragma mark -------- Auto Methods --------

- (CGFloat)distanceMutiple
{
    if (ScreenWidth == 320)
        return 1.5f;
    
    return 1.0f;
}

// 在一段时间内没有收到有效的beacon号码，
- (void)postNoBeaconNoti
{
    //    [[NSNotificationCenter defaultCenter] postNotificationName:No_Beacon_Receive_For_Notification object:nil];
}

#pragma mark
#pragma mark -------- Dealloc Methods --------

- (void)noBeaconTimeClean
{
    self.noBeaconStartTime = nil;
    self.noBeaconEndTime = nil;
}

- (void)cleanPlayNum
{ self.beaconNum = nil; }

- (void)cleanVarables
{
    [self.beacons removeAllObjects];
    self.beacons = nil;
    
    [self stopRangingAllRegions];
    self.locationManager = nil;
    
    [self.rangedRegions removeAllObjects];
    self.rangedRegions = nil;
    
    [self.topBeaconArray removeAllObjects];
    self.topBeaconArray = nil;
    self.noBeaconStartTime = nil;
    self.noBeaconEndTime = nil;
    [self.valideVCSet removeAllObjects];
    self.valideVCSet = nil;
    [self cleanPlayNum];
}

- (void)dealloc
{
    [self cleanVarables];
    _nowVCString = nil;
}


@end
